package org.study.r2dbc.boot.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.stereotype.Service;
import org.study.r2dbc.boot.model.User;
import org.study.r2dbc.boot.repository.UserRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 作用描述
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2025年04月02日
 */
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Service
public class UserServiceImplByEntityTemplate implements UserServiceByEntityTemplate {
    private final UserRepository userRepository;
    private final R2dbcEntityTemplate r2dbcEntityTemplate;

    @Override
    public Flux<User> findActiveUsers() {
        return r2dbcEntityTemplate.select(User.class)
                .from("t_user")
                .matching(Query.query(Criteria.where("active").is(true)))
                .all();
    }

    @Override
    public Flux<User> findUsers(String name, Boolean active) {
        Criteria criteria = Criteria.empty();
        if (StringUtils.isNotBlank(name)) {
            criteria = criteria.and("name").like("%" + name + "%");
        }
        if (active != null) {
            criteria = criteria.and("active").is(active);
        }
        return r2dbcEntityTemplate.select(User.class)
                .from("t_user")
                .matching(Query.query(criteria))
                .all();
    }

    @Override
    public Mono<User> saveUser1(User user) {
        return r2dbcEntityTemplate.insert(user);
    }

    @Override
    public Mono<User> saveUser2(User user) {
        // 直接保存，假设调用方已确保ID不存在
        return r2dbcEntityTemplate.insert(user)
                .onErrorResume(ex -> {
                    // 处理可能的主键冲突
                    if (StringUtils.isNotBlank(ex.getMessage()) && ex.getMessage().toLowerCase().contains("duplicate key")) {
                        return Mono.error(new RuntimeException("当前用户ID：" + user.getId() + "已存在"));
                    }
                    return Mono.error(ex);
                });
    }

    @Override
    public Mono<User> saveUser3(User user) {
        // 先检查ID是否已存在
        return userRepository.existsById(user.getId())
                .flatMap(exists -> {
                    if (exists) {
                        return Mono.error(new RuntimeException("当前用户ID：" + user.getId() + "已存在"));
                    }
                    return r2dbcEntityTemplate.insert(user);
                });
    }
}
